#include "Thread.hpp"

using namespace myThread;
#include <vector>

// 放在main函数中不好操作


class ThreadTask{
public:

    ThreadTask(int taski, int cnt = 10)
        :_taski(taski),
        _cnt(cnt),
        _exec_res(0),
        _tid(0),
        _name("")
    {}

    ~ThreadTask(){}

    void Execute(){
        _exec_res = _cnt + 5;
    }


    int _taski; 
    int _cnt;
    int _exec_res;
    pthread_t _tid;
    std::string _name;
};

std::vector<Thread<ThreadTask>> _threads;
std::vector<ThreadTask> _threadtask;

void Routine(ThreadTask data){
    // 沉睡一下，保证线程启动的时候，数据已经设置到thread_task数组了
    sleep(1);

    data._name = _threadtask[data._taski]._name;
    data._tid = _threadtask[data._taski]._tid;

    int cnt = data._cnt;
    while(cnt--){
        std::cout << data._name << "thread, tid is " << data._tid << std::endl;
        sleep(1); 
    }

    std::cout << data._name << " : " << std::endl;
    std::cout << "执行Execute任务" << std::endl; 
    data.Execute();
    std::cout << "执行任务结果" << data._exec_res << std::endl;
}

int main(){

    //std::vector<Thread<ThreadTask>> _threads;
    //std::vector<ThreadTask> _threadtask;

    // 创建一批线程
    for(int i = 0; i < 10; ++i){
        ThreadTask thread_task(i, 5);
        _threadtask.push_back(thread_task);

        Thread<ThreadTask> thread(Routine, thread_task);
        _threads.push_back(thread);


        // 错误写法！！！ 这里push_back调用了移动构造(Thread内没写拷贝 / 移动构造)
        // 移动构造本质是掠夺资源 -> 一旦访问被移动的有资源的类型(function...) -> 线程崩溃！
        // 所以，如果写下面两句代码
        // 第一个线程跑起来一会儿，就访问到了 thread_task._tid = thread.GetTid();
        // 访问到了被移动的资源 -> 直接崩
        /* thread_task._name = thread.GetName();
        thread_task._tid = thread.GetTid(); */


        // 这样写不用怕报错 -> 因为资源被略到数组上了
        /* thread_task._name = _threads[i].GetName();
        thread_task._tid = _threads[i].GetTid(); */
        // 但是，这样子即使线程跑起来了，也没办法让Routine执行的时候拿到这里thread_task修改的数据
        // 因为，Thread<ThreadTask> thread(Routine, thread_task);创建的时候
        // 底层保存的T _data 其实是thread_task的拷贝
        // 我们在主线程中对thread_task修改，其他线程中保存的都是拷贝，所以是没办法给到那里的！
    }

    // 启动线程
    for(int i = 0; i < _threads.size(); ++i){
        _threads[i].Start();
        _threadtask[i]._name = _threads[i].GetName();
        _threadtask[i]._tid = _threads[i].GetTid();
        sleep(1); // 让线程启动带有一定延迟
    } 

    /* for(int i = 0; i < _threads.size(); ++i){
        _threads[i].Detach();
    } */

    for(int i = 0; i < _threads.size(); ++i){
        _threads[i].Join();
    }

    return 0;
}